/******************************************************************************/
/* RT_Agent.C: Real-Time Agent V2.12                                          */
/******************************************************************************/
/*                                                                            */                           
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2006-07 Keil - An ARM Company. All rights reserved.          */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/

#pragma thumb     /* Force thumb mode */
#pragma O3        /* Force optimisation level 3 */
#pragma Otime     /* Force optimisation for time */

/*==============================================================================
   DO NOT EDIT THIS FILE (unless using custom hardware)
==============================================================================*/

// Real-Time Agent Version
#define __RTA_VERSION_MAJ     2
#define __RTA_VERSION_MIN     12
#define __RTA_VERSION         (__RTA_VERSION_MAJ << 4) | __RTA_VERSION_MIN

/*==============================================================================
   Real-Time Agent Includes
==============================================================================*/

#include "RT_Agent.H"

/*==============================================================================
   Configuration defines check
==============================================================================*/

// <e0>Real-Time Agent
// <i>Enable Real-Time Agent to obtain run-time debug information.
#ifndef __RTA_ENABLED
 #error Real-Time Agent: __RTA_ENABLED not defined!
#endif

#ifndef __RTA_HW_TYPE
 #error Real-Time Agent: __RTA_HW_TYPE not defined!
#endif

#ifndef __RTA_OUT_SIZE_BYTES
 #error Real-Time Agent: __RTA_OUT_SIZE_BYTES not defined!
#endif

#ifndef __RTA_NO_MEM_FLAG
 #error Real-Time Agent: __RTA_NO_MEM_FLAG not defined!
#endif

#ifndef __RTA_TERM_SUPPORT
 #error Real-Time Agent: __RTA_TERM_SUPPORT not defined!
#endif

#ifndef __RTA_TERM_ECHO
 #error Real-Time Agent: __RTA_TERM_ECHO not defined!
#endif

#ifndef __RTA_TERM_W_BLOCKING
 #error Real-Time Agent: __RTA_TERM_W_BLOCKING not defined!
#endif

#ifndef __IO_RETARGET_ENABLED
 #error Real-Time Agent: __IO_RETARGET_ENABLED not defined!
#endif

#ifndef __IO_RETARGET_STDIO_ROUTE
 #error Real-Time Agent: __IO_RETARGET_STDIO_ROUTE not defined!
#endif

#ifndef __IO_RETARGET_FOPEN_ETC_ENABLED
 #error Real-Time Agent: __IO_RETARGET_FOPEN_ETC_ENABLED not defined!
#endif

#ifndef __RTA_DEC
 #error Real-Time Agent: __RTA_DEC not defined!
#endif

#ifndef __RTA_TERM_IN_SIZE
 #error Real-Time Agent: __RTA_TERM_IN_SIZE not defined!
#endif

#ifndef RTA_EXT_DABT_ERROR
 #define RTA_EXT_DABT_ERROR             0
#endif


/*==============================================================================
   Checks for valid RTA and retargetting configurations
==============================================================================*/

/* If RTA Terminal is defined, Retargetting must also be defined */
#if ((__RTA_ENABLED) && (__RTA_TERM_SUPPORT)) 
  #if (__IO_RETARGET_ENABLED == 0)
    #error Real-Time Agent Terminal Support is enabled, but I/O Retargetting is not. I/O Retargetting is required to support the Real-Time Agent Terminal. Enable I/O Retargetting or disable Real-Time Agent Terminal support.
  #endif
#endif

/* If STDIO route is to RTA, then both RTA and RTA Terminal must be defined */
#if ((__IO_RETARGET_ENABLED) && (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA))
  #if ((__RTA_ENABLED == 0) || ((__RTA_ENABLED == 1) && (__RTA_TERM_SUPPORT == 0)))  
    #error STDIO is redirected to the Real-Time Agent Terminal, but Real-Time Agent Terminal Support is not enabled. Enable Real-Time Agent Terminal support, or redirect STDIO elsewhere.
  #endif
#endif


/*==============================================================================
   RTA Hardware Specific Section 
==============================================================================*/

#if ((__RTA_HW_TYPE == RTA_HW_LPC21xx) || (__RTA_HW_TYPE == RTA_HW_LPC22xx)) 

#include <LPC21xx.H>                /* LPC21xx definitions  */

#define RTA_EXPORT_IRQS   0

#define TX_IRQ_INIT()     VICVectAddr13 = (unsigned long)RTA_tx_word; \
                          VICVectCntl13 = 0x20 | 3;                      
#define TX_IRQ_ACK()      VICVectAddr = 0;
#define TX_IRQ_ENABLE()   VICIntEnable = 0x00000008;
#define TX_IRQ_DISABLE()  VICIntEnClr = 0x00000008;
                                            
#define RX_IRQ_INIT()     VICVectAddr14 = (unsigned long)RTA_rx_word; \
                          VICVectCntl14 = 0x20 | 2;               
#define RX_IRQ_ACK()      VICVectAddr = 0; 
#define RX_IRQ_ENABLE()   VICIntEnable = 0x00000004;
#define RX_IRQ_DISABLE()  VICIntEnClr = 0x00000004;

#define DEF_IRQ_INIT()    VICDefVectAddr= (unsigned long)RTA_def_irq;
#define DEF_IRQ_ACK()     VICVectAddr = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }
 

#elif (__RTA_HW_TYPE == RTA_HW_LPC23xx) 

#include <LPC23xx.H>                /* LPC23xx definitions  */

#define RTA_EXPORT_IRQS   0

#define TX_IRQ_INIT()     VICVectAddr3 = (unsigned long)RTA_tx_word; \
                          VICVectCntl3 = 0x0f;                      
#define TX_IRQ_ACK()      VICVectAddr = 0;
#define TX_IRQ_ENABLE()   VICIntEnable = 0x00000008;
#define TX_IRQ_DISABLE()  VICIntEnClr = 0x00000008;
                                            
#define RX_IRQ_INIT()     VICVectAddr2 = (unsigned long)RTA_rx_word; \
                          VICVectCntl2 = 0x0f;               
#define RX_IRQ_ACK()      VICVectAddr = 0; 
#define RX_IRQ_ENABLE()   VICIntEnable = 0x00000004;
#define RX_IRQ_DISABLE()  VICIntEnClr = 0x00000004;

#define DEF_IRQ_INIT()    
#define DEF_IRQ_ACK()     

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }
 
 
#elif (__RTA_HW_TYPE == RTA_HW_STR91x)

#include <91x_lib.h> 		    /* STR91x definitions        */ 

#define RTA_EXPORT_IRQS   0

#define TX_IRQ_INIT()     VIC0->VAiR[3] = (unsigned int)RTA_tx_word; \
                          VIC0->INTSR  &= ~(0x01 << (ARMTX_ITLine)); \
                          VIC0->VCiR[3] =    0x20 | (ARMTX_ITLine); 
#define TX_IRQ_ACK()      VIC0->VAR = 0; \
                          VIC1->VAR = 0;
#define TX_IRQ_ENABLE()   VIC0->INTER  |=  (0x01 << (ARMTX_ITLine));
#define TX_IRQ_DISABLE()  VIC0->INTECR |=  (0x01 << (ARMTX_ITLine));
                                                            
#define RX_IRQ_INIT()     VIC0->VAiR[2] = (unsigned int)RTA_rx_word; \
                          VIC0->INTSR  &= ~(0x01 << (ARMRX_ITLine)); \
                          VIC0->VCiR[2] =    0x20 | (ARMRX_ITLine);                         
#define RX_IRQ_ACK()      VIC0->VAR = 0; \
                          VIC1->VAR = 0;
#define RX_IRQ_ENABLE()   VIC0->INTER  |=  (0x01 << (ARMRX_ITLine));
#define RX_IRQ_DISABLE()  VIC0->INTECR |=  (0x01 << (ARMRX_ITLine));

#define DEF_IRQ_INIT()    VIC0->DVAR    = (unsigned long)RTA_def_irq;
#define DEF_IRQ_ACK()     VIC0->VAR = 0; \
                          VIC1->VAR = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }


#elif (__RTA_HW_TYPE == RTA_HW_AT91SAM7Sx)

#include <AT91SAM7S64.H>  	    /* AT91SAM7Sx definitions        */ 

#define RTA_EXPORT_IRQS   1      

#define TX_IRQ_INIT()     // In user code
#define TX_IRQ_ACK()      // In user code
#define TX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_TX;   
#define TX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_TX;
           
#define RX_IRQ_INIT()     // In user code          
#define RX_IRQ_ACK()      // In user code          						   
#define RX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_RX;
#define RX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_RX;
       
#define DEF_IRQ_INIT()    *AT91C_AIC_SPU = (unsigned long) RTA_def_irq;
#define DEF_IRQ_ACK()     *AT91C_AIC_EOICR = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }


#elif (__RTA_HW_TYPE == RTA_HW_AT91SAM7Xx)

#include <AT91SAM7X256.H>       /* AT91SAM7Xx definitions          */

#define RTA_EXPORT_IRQS   1      

#define TX_IRQ_INIT()     // In user code
#define TX_IRQ_ACK()      // In user code
#define TX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_TX;   
#define TX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_TX;
           
#define RX_IRQ_INIT()     // In user code          
#define RX_IRQ_ACK()      // In user code          						   
#define RX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_RX;
#define RX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_RX;
       
#define DEF_IRQ_INIT()    *AT91C_AIC_SPU = (unsigned long) RTA_def_irq;
#define DEF_IRQ_ACK()     *AT91C_AIC_EOICR = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }


#elif (__RTA_HW_TYPE == RTA_HW_AT91SAM9261)

#include <AT91SAM9261.H>        /* AT91SAM9261 definitions          */

#define RTA_EXPORT_IRQS   1      

#define TX_IRQ_INIT()     // In user code
#define TX_IRQ_ACK()      // In user code
#define TX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_TX;   
#define TX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_TX;
           
#define RX_IRQ_INIT()     // In user code          
#define RX_IRQ_ACK()      // In user code          						   
#define RX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_RX;
#define RX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_RX;
       
#define DEF_IRQ_INIT()    *AT91C_AIC_SPU = (unsigned long) RTA_def_irq;
#define DEF_IRQ_ACK()     *AT91C_AIC_EOICR = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }


#elif (__RTA_HW_TYPE == RTA_HW_AT91SAM9263)

#include <AT91SAM9263.H>        /* AT91SAM9263 definitions          */

#define RTA_EXPORT_IRQS   1      

#define TX_IRQ_INIT()     // In user code
#define TX_IRQ_ACK()      // In user code
#define TX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_TX;   
#define TX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_TX;
           
#define RX_IRQ_INIT()     // In user code          
#define RX_IRQ_ACK()      // In user code          						   
#define RX_IRQ_ENABLE()   *AT91C_DBGU_IER = AT91C_US_COMM_RX;
#define RX_IRQ_DISABLE()  *AT91C_DBGU_IDR = AT91C_US_COMM_RX;
       
#define DEF_IRQ_INIT()    *AT91C_AIC_SPU = (unsigned long) RTA_def_irq;
#define DEF_IRQ_ACK()     *AT91C_AIC_EOICR = 0;

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }

#elif (__RTA_HW_TYPE == RTA_HW_POLLED)

#define RTA_EXPORT_IRQS   1      

#define TX_IRQ_INIT()     // Not used in polled mode
#define TX_IRQ_ACK()      // Not used in polled mode
#define TX_IRQ_ENABLE()   RTA_irq_enable_ext()      // Implemented by user
#define TX_IRQ_DISABLE()  RTA_irq_disable_ext()     // Implemented by user
           
#define RX_IRQ_INIT()     // Not used in polled mode
#define RX_IRQ_ACK()      // Not used in polled mode
#define RX_IRQ_ENABLE()   // Not used in polled mode
#define RX_IRQ_DISABLE()  // Not used in polled mode
       
#define DEF_IRQ_INIT()    // In user code
#define DEF_IRQ_ACK()     // In user code

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }

#define TX_WORD_POSS      __asm { MRC     p14,0,r,c0,c0   } \
                          __asm { AND     r,r,#0x02       } \
                          __asm { EOR     r,r,#0x02       }
#define RX_WORD_POSS      __asm { MRC     p14,0,r,c0,c0   } \
                          __asm { AND     r,r,#0x01       }


#elif (__RTA_HW_TYPE == RTA_HW_CUSTOM)  /* Custom hardare */

#define RTA_EXPORT_IRQS   0

#define TX_IRQ_INIT()     // User to implement  
#define TX_IRQ_ACK()      // User to implement
#define TX_IRQ_ENABLE()   // User to implement
#define TX_IRQ_DISABLE()  // User to implement                                                             

#define RX_IRQ_INIT()     // User to implement          
#define RX_IRQ_ACK()      // User to implement
#define RX_IRQ_ENABLE()   // User to implement
#define RX_IRQ_DISABLE()  // User to implement

#define DEF_IRQ_INIT()    // User to implement
#define DEF_IRQ_ACK()     // User to implement

#define TX_WORD()         __asm { MCR     p14, 0, tx_word, c1, c0 }      
#define RX_WORD()         __asm { MRC     p14, 0, rx_word, c1, c0 }

#endif  /* __RTA_HW_TYPE */


/*==============================================================================
   Helper MACROs
==============================================================================*/

// IO Retargetting is redirected to a useful location
#define __IO_RETARGET_STDIO_IN_USE  ((__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_COM_1) || (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA))


/*==============================================================================
   Real-Time Agent Definitions
==============================================================================*/

#if (__RTA_TERM_SUPPORT)
  #include <stdio.h>
#endif

// Protocol Constants
#define RTA_TX_MAGIC_NO      0xFA
#define RTA_INITIAL_SEQ_NO   0xCE
#define RTA_SYNC_WORD        0xFA00CE00
#define RTA_SYNC_MSG_SIZE    2
#define RTA_REQ_RSP_BIT      0x80
#define RTA_TERM_RETRY_COUNT 500
#define RTA_MAX_DATA_LEN     120          
#define RTA_MAX_MSG_LEN      (RTA_MAX_DATA_LEN + 8)  // Message = Header + Data + Checksum = 128 (32 words)

// Buffer masks
#define RTA_OUT_MASK         (__RTA_OUT_SIZE-1ul)
#define RTA_TERM_IN_MASK     (__RTA_TERM_IN_SIZE-1ul)

// Internal Status flags
#define FLAG_DABT_PROTECT    1

// Functional macros
#define RTA_RESET()          {unsigned int iZero = 0;                          \
                              RTA_Msg(RTA_CMD_UNKNOWN, &iZero, RTA_SHORT_MSG); \
                              rta.status &= ~RTA_STATUS_CONNECTED;}                                         // Reset RTA communications
                             
#define RTA_SYNC()           RTA_Msg(RTA_CMD_SYNC, (unsigned int *)&sync_msg_data, RTA_SYNC_MSG_SIZE);      // Sync  RTA communications
                             
#define RTA_IS_INIT         (rta.status & RTA_STATUS_INTIALIZED == RTA_STATUS_INTIALIZED)                   // RTA is initialised
#define RTA_BUFFER_OVERRUN  (rta.status & RTA_STATUS_BUF_OVERRUN == RTA_STATUS_BUF_OVERRUN)                 // RTA has a buffer overrun
#define RTA_HOST_CONNECTED  (rta.status & RTA_STATUS_CONNECTED == RTA_STATUS_CONNECTED)                     // RTA host is connected

// RTA Internal (private) command definitions
typedef enum __RTA_INTERNAL_COMMANDS
{
  RTA_CMD_SYNC            = 0x00,

  /* Normal internal command codes */
  RTA_CMD_ERROR           = 0x01,
  RTA_CMD_TERM_DATA       = 0x02,
  RTA_CMD_SET_ADDRESS     = 0x03,
  RTA_CMD_MEM_WRITE_8     = 0x04,
  RTA_CMD_MEM_WRITE_16    = 0x05,
  RTA_CMD_MEM_WRITE_32    = 0x06,
  RTA_CMD_RTX_TASK_CHANGE = 0x0A,
  RTA_CMD_RTX_TASK_SWITCH = 0x0B,
  
  /* Synchronous response command codes (must have bit 7 set) */
  RTA_CMD_GET_VERSION     = 0x80,
  RTA_CMD_MEM_READ_8      = 0x81,
  RTA_CMD_MEM_READ_16     = 0x82,
  RTA_CMD_MEM_READ_32     = 0x83,
  RTA_CMD_RTX_MON_START   = 0x84,
  RTA_CMD_RTX_MON_STOP    = 0x85,
    
  /* Speical Unknown command definition for reset */
  RTA_CMD_UNKNOWN         = 0x0F     
} RTA_INTERNAL_COMMANDS;

// RTA message formats
typedef enum __MSG_FORMAT {
  MSG_FORMAT_SHORT = 0,
  MSG_FORMAT_LONG,
  MSG_FORMAT_TASKSWITCH
} MSG_FORMAT;

// RTA state machine states
typedef enum __RTA_STATES
{
  RTA_STATE_COMMAND = 0,
  RTA_STATE_ADDRESS,
  RTA_STATE_MEM_WRITE_8,
  RTA_STATE_MEM_WRITE_16,
  RTA_STATE_MEM_WRITE_32,
  RTA_STATE_COUNT                 // Always leave at end
} RTA_STATES;

// RTA message header split
typedef struct __msg_header_t {
  unsigned int length     : 8;    // 0x000000XX
  unsigned int seq_no     : 8;    // 0x0000XX00
  unsigned int type       : 8;    // 0x00XX0000
  unsigned int fixed      : 8;    // 0xXX000000
} msg_header_t;

// RTA message header union
typedef union __msg_header_u {
    msg_header_t split;
    unsigned int raw;
} msg_header_u;

// RTA message structure
typedef struct __RTA_msg_t {
  msg_header_u header;
  const unsigned int* data;
  unsigned int checksum;
} RTA_msg_t;

// RTA RX state machine function pointers typedef 
typedef void (*state_fp)(unsigned int rx_word);

// RTA output buffer
typedef struct __RTA_out_t {
  unsigned int data[__RTA_OUT_SIZE];
  unsigned int wr_idx;
  unsigned int rd_idx;
} RTA_out_t;

// RTA Terminal Emulator buffer
typedef struct __RTA_term_in_t {
  unsigned char data[__RTA_TERM_IN_SIZE];
  unsigned char wr_idx;
  unsigned char rd_idx;
} RTA_term_in_t;

// RTA structure
typedef struct __RTA_t {
  unsigned int stateMachine;      // RTA state machine state
  unsigned char tx_seq_no;        // Transmit sequence number
  unsigned int status;            // RTX status flags

  unsigned int rw_addr;           // Read/Write address
  unsigned int w_end_addr;        // Write end address

  RTA_out_t out;                  // Output buffer
} RTA_t;

/*==============================================================================
   Real-Time Agent Exported Variables
==============================================================================*/

// File pointers for the RTA terminal emulation (RTA_printf, etc)
void * __RTA_fpDbgIn = 0;
void * __RTA_fpDbgOut = 0;

// RTA Flags
// NOTE:   This variable cannot be static because it is required by __asm functions
// FORMAT: 0x0000000(0000000 | Data Abort protection flag)
volatile int __RTA_Flags = 0; 

/*==============================================================================
   Real-Time Agent Version Number variable
==============================================================================*/                 

#if (__RTA_ENABLED)
__attribute__((used)) const unsigned int __rta_version = __RTA_VERSION; // Real-Time Agent version
#else
__attribute__((used)) const unsigned int __rta_version = 0;             // Zero indicates Real-Time Agent compiled out
#endif

#if (__RTA_ENABLED)
/*==============================================================================
   RTA MAIN CODE (ENABLED CODE SECTION)
==============================================================================*/                 

// RTA variables	
static volatile RTA_t rta;                // Agent state structure
            
#if (__RTA_TERM_SUPPORT)
  static volatile RTA_term_in_t term_in;  // Terminal Emulator input buffer
#endif

// Function prototypes
static RTA_STATUS send_msg_raw (RTA_msg_t *msg, MSG_FORMAT format);
#if (RTA_EXPORT_IRQS)
void RTA_rx_word_ext (void);
void RTA_tx_word_ext (void);
#else
static __irq void RTA_rx_word (void);
static __irq void RTA_tx_word (void);
#endif
static __irq void RTA_def_irq (void);
static void main_cmd(unsigned int rx_word);
static void main_addr(unsigned int rx_word);
static void main_mem_rd_32(unsigned int rx_word);
static void main_mem_wr_8(unsigned int rx_word);
static void main_mem_wr_16(unsigned int rx_word);
static void main_mem_wr_32(unsigned int rx_word);
__asm unsigned int __RTA_rd_adr (unsigned int *addrData, unsigned int r1);
__asm void __RTA_wr_8 (unsigned int addrData, unsigned int data);
__asm void __RTA_wr_16 (unsigned int addrData, unsigned int data);
__asm void __RTA_wr_32 (unsigned int addrData, unsigned int data);


// RTA RX state machine function pointers 
static state_fp const state_funcs[RTA_STATE_COUNT] = {
                                            main_cmd,
                                            main_addr,
                                            main_mem_wr_8,
                                            main_mem_wr_16,
                                            main_mem_wr_32
                                            };

static const unsigned int sync_msg_data[RTA_SYNC_MSG_SIZE] = {0x52415365,
                                                              0x77656C6C};


/* Buffer read / write macros */

/* RTA Host out buffer */
#define OUT_BUF_RESET()     (rta.out.rd_idx = rta.out.wr_idx = 0)
#define OUT_BUF_WR(dataOut) (rta.out.data[RTA_OUT_MASK & rta.out.wr_idx++] = (dataOut))
#define OUT_BUF_RD()        (rta.out.data[RTA_OUT_MASK & rta.out.rd_idx++])   
#define OUT_BUF_EMPTY()     (rta.out.rd_idx == rta.out.wr_idx)
#define OUT_BUF_FULL()      (rta.out.rd_idx == rta.out.wr_idx+1)

/* RTA Host terminal in buffer */
#define TERM_IN_BUF_RESET()     (term_in.rd_idx = term_in.wr_idx = 0)
#define TERM_IN_BUF_WR(dataOut) (term_in.data[RTA_TERM_IN_MASK & term_in.wr_idx++] = (dataOut))
#define TERM_IN_BUF_RD()        (term_in.data[RTA_TERM_IN_MASK & term_in.rd_idx++])
#define TERM_IN_BUF_EMPTY()     (term_in.rd_idx == term_in.wr_idx)
#define TERM_IN_BUF_FULL()      (term_in.rd_idx == term_in.wr_idx+1)
#define TERM_IN_BUF_NOT_EMPTY() ((term_in.wr_idx - term_in.rd_idx) & RTA_TERM_IN_MASK)


/*==============================================================================
   RTA External Functions 
==============================================================================*/

/*
 *  Initialise Real-Time Agent
 *    Parameters:     None
 *    Return Value:   RTA_STATUS (0 = OK)
 */
RTA_STATUS RTA_Init (void) {

  if (!RTA_IS_INIT) {                  
    DEF_IRQ_INIT();                             // Set up the default (suprious) interrupt 
    TX_IRQ_INIT();                              // Set up the RTA TX interrupt 
    RX_IRQ_INIT();                              // Set up the RTA RX interrupt
                                     
    rta.stateMachine = RTA_STATE_COMMAND;       // Reset the states and buffer pointers
    rta.tx_seq_no = RTA_INITIAL_SEQ_NO;
    OUT_BUF_RESET();                            // Set buffer empty conditions
    rta.status = 0;                             // Clear status flags

#if (__RTA_TERM_SUPPORT)
    TERM_IN_BUF_RESET();                        // Reset terminal buffer    
    __RTA_fpDbgIn = fopen("RTADBGIN", "r");     // Open RTA dbg in for reading               
    __RTA_fpDbgOut = fopen("RTADBGOUT", "w");   // Open RTA dbg out for writing                           

#endif /* #if (__RTA_TERM_SUPPORT)*/

    RX_IRQ_ENABLE();                            // Enable RTA Rx Interrupt
    rta.status |= RTA_STATUS_INTIALIZED;        // Set initialised flag
  }

  return (RTA_OK);
}

/*
 *  Get the Real-Time Agent status
 *    Parameters:     None
 *    Return Value:  Real-Time Agent status flags
 */
__RTA_DEC unsigned int RTA_Status (void) {
  return (rta.status);
}

/*
 *  Send a message to the host via Real-Time Agent
 *    Parameters:     type:   type code of command/message
 *                    data:   pointer to message buffer to send
 *                    length: length of data message buffer in words,
 *                            or 0 for a short message
 *    Return Value:   RTA_STATUS (0 = OK)
 */
__RTA_DEC RTA_STATUS RTA_Msg (unsigned int type, unsigned int *data, unsigned int length) {
  RTA_STATUS status = RTA_OK;
  MSG_FORMAT format;
  RTA_msg_t  msg;

  if (RTA_IS_INIT) {
  
    // Create header
    msg.header.split.type = type;
  
    // Add data
    if (length) {                               // Long Message    
      msg.header.split.length = length;
      msg.data = data;
      format = MSG_FORMAT_LONG;
    }
    else {                                      // Short Message
      if (data == 0) return (RTA_ERR_PARAM);    // Parameter check
      msg.header.split.length = *data;
      format = MSG_FORMAT_SHORT;                // Indicates short message    
    }
        
    status = send_msg_raw(&msg, format);        // Send message

  }
  else {
    status = RTA_ERR_NOT_INIT;
  }

  return (status);
}

/*
 *  Send RTX Kernel task switch information to the host via Real-Time Agent
 *    Parameters:     tsk:    packed task switch message
 *    Return Value:   RTA_STATUS (0 = OK)
 */
__RTA_DEC void RTA_Task_Mon (unsigned int tsk) {
  RTA_msg_t  msg;

	tsk &= 0x7FFFFFFF; 
  
#ifdef __BIG_ENDIAN 
  msg.header.raw = __rev(tsk);     // If big endian, must swap to keep procotol happy (use ARM intrinsic)
#else
  msg.header.raw = tsk;            // If little endian, no need to swap
#endif
   
	send_msg_raw(&msg, MSG_FORMAT_TASKSWITCH);
}

/*==============================================================================
   RTA Receive Functions
==============================================================================*/

/*  
 *  Handle a read/write address from the host
 *    Parameters:      rx_word:   received address word
 *    Return Value:    None 
 */
static void main_addr(unsigned int rx_word) {
  rta.rw_addr = rx_word;
  rta.stateMachine = RTA_STATE_COMMAND;
}

/*
 *  Handle a mem read from the host
 *    Parameters:      length:   length of data to read in words
 *    Return Value:    None
 */
static void main_mem_rd_32(unsigned int length){
  // Return the data that was requested to read
  RTA_Msg(RTA_CMD_MEM_READ_32, 
          (unsigned int *)rta.rw_addr, 
          length);
}

/*
 *  Handle a 8-bit mem write from the host
 *    Parameters:      data:   data to write
 *    Return Value:    None
 */
static void main_mem_wr_8(unsigned int data) {
  unsigned int byte = 0;

  // Write data (8-bit)
  __RTA_Flags |= FLAG_DABT_PROTECT;
  while ((rta.rw_addr < rta.w_end_addr) && (byte < 32)) {
    __RTA_wr_8 (rta.rw_addr, (data >> byte));
    rta.rw_addr += sizeof(unsigned char);
    byte+=8;
  }
  __RTA_Flags &= ~(FLAG_DABT_PROTECT);

  // Switch back to command mode when write finished
  if (rta.rw_addr >= rta.w_end_addr) {
    rta.stateMachine = RTA_STATE_COMMAND;  
  }
}

/*
 *  Handle a 16-bit mem write from the host
 *    Parameters:      data:   data to write
 *    Return Value:    None
 */
static void main_mem_wr_16(unsigned int data) {
  unsigned int halfword = 0;

  // Write data (16-bit)
  __RTA_Flags |= FLAG_DABT_PROTECT;
  while ((rta.rw_addr < rta.w_end_addr) && (halfword < 32)) {
    __RTA_wr_16 (rta.rw_addr, (data >> halfword));
    rta.rw_addr += sizeof(unsigned short);
    halfword+=16;
  }
  __RTA_Flags &= ~(FLAG_DABT_PROTECT); 

  // Switch back to command mode when write finished
  if (rta.rw_addr >= rta.w_end_addr) {
    rta.stateMachine = RTA_STATE_COMMAND;  
  }
}

/*
 *  Handle a 32-bit mem write from the host
 *    Parameters:      data:   data to write
 *    Return Value:    None
 */
static void main_mem_wr_32(unsigned int data) {
  // Write data (32-bit)
  __RTA_Flags |= FLAG_DABT_PROTECT;
  __RTA_wr_32 (rta.rw_addr, data);
  rta.rw_addr += sizeof(unsigned int);
  __RTA_Flags &= ~(FLAG_DABT_PROTECT);

  // Switch back to command mode when write finished
  if (rta.rw_addr >= rta.w_end_addr) {
    rta.stateMachine = RTA_STATE_COMMAND;  
  }
}

/*
 *  Handle commands from the host
 *    Parameters:      rx_word:   command word received
 *                     val:   Data
 *    Return Value:    None
 */
static void main_cmd(unsigned int rx_word) {

  /* Could check sequence number and magic number here, but
     do not because of the processing time cost */
  switch ((rx_word >> 16) & 0xFF) {                    // Message type
    case RTA_CMD_SYNC:
      if (rx_word == RTA_SYNC_WORD) {
        RTA_SYNC();
      }
      else {
        RTA_RESET();
      } 
    break;

    case RTA_CMD_GET_VERSION:
      rta.status |= RTA_STATUS_CONNECTED;
      RTA_Msg(RTA_CMD_GET_VERSION, (unsigned int *)&__rta_version, RTA_SHORT_MSG);
    break;

    case RTA_CMD_TERM_DATA:
#if (__RTA_TERM_SUPPORT)
      // Pass term data to term in buffer
      TERM_IN_BUF_WR(rx_word & 0x000000FF);
#endif
    break;

    case RTA_CMD_SET_ADDRESS:
      rta.stateMachine = RTA_STATE_ADDRESS;
    break;

    case RTA_CMD_MEM_READ_32:                
      main_mem_rd_32(rx_word & 0x000000FF);
    break;  

    /* RTX monitoring messages */
#if 0   // Not implemented
    case RTA_CMD_RTX_MON_START:
      rta.rtx_mon = 1;
    break;

    case RTA_CMD_RTX_MON_STOP:
      rta.rtx_mon = 0;
    break;
#endif

    /* Special mode messages */
    case RTA_CMD_MEM_WRITE_8:
      rta.w_end_addr = rta.rw_addr + ((rx_word & 0x000000FF)); 
      rta.stateMachine = RTA_STATE_MEM_WRITE_8;                
    break;

    case RTA_CMD_MEM_WRITE_16:
      rta.w_end_addr = rta.rw_addr + ((rx_word & 0x000000FF) << 1); 
      rta.stateMachine = RTA_STATE_MEM_WRITE_16;                
    break;

    case RTA_CMD_MEM_WRITE_32:
      rta.w_end_addr = rta.rw_addr + ((rx_word & 0x000000FF) << 2); 
      rta.stateMachine = RTA_STATE_MEM_WRITE_32;                
    break;

    default:
      RTA_RESET();
  }
}

/*
 *  RTA Receive word possible
 *    Parameters:      None
 *    Return Value:    0 = Not possible, Non-zero = possible
 */
#if (__RTA_HW_TYPE == RTA_HW_POLLED)
#pragma push
#pragma arm
static __forceinline int RTA_rx_word_poss (void)
{
  int r;
  RX_WORD_POSS;
  return (r);
}
#pragma pop
#endif /* if (__RTA_HW_TYPE == RTA_HW_POLLED) */

/*
 *  RTA Receive word (interrupt context)
 *    Parameters:      None
 *    Return Value:    None
 */
#pragma push
#pragma arm
#if (RTA_EXPORT_IRQS)
void RTA_rx_word_ext (void)
#else
static __irq void RTA_rx_word (void)
#endif
{
  unsigned int rx_word;

  RX_IRQ_ACK();                               // Acknowledge Interrupt

#if (__RTA_HW_TYPE == RTA_HW_POLLED)
  if (RTA_rx_word_poss()) {                   // Check RX buffer free
#endif
    RX_WORD();                                // Read word from hardware                                
    state_funcs[rta.stateMachine](rx_word);   // Call state machine
#if (__RTA_HW_TYPE == RTA_HW_POLLED)
  }
#endif
}
#pragma pop

/*==============================================================================
   RTA Transmit Functions
==============================================================================*/

/*
 *  Send a message to the host
 *    Parameters:      msg:     pointer to the message
 *                     //format:  format of the message (LONG or SHORT)
 *                     Message format is now determined by a NULL data pointer
 *    Return Value:    RTA_STATUS (0 = OK)
 */
#define   __RTA_ARM_MODE_MASK   0x1F
#define   __RTA_ARM_MODE_USER   0x10

static RTA_STATUS send_msg_raw (RTA_msg_t *msg, MSG_FORMAT format) {
  RTA_STATUS retVal = RTA_OK;
  unsigned int type = msg->header.split.type;
  const unsigned int *data = msg->data;                   // Local pointer to the data
  unsigned int length = msg->header.split.length;
  unsigned int bufLeft, bufNeeded;   
#ifdef __RTX
  register unsigned int R_cpsr __asm("cpsr"); 
  int bUserMode = ((R_cpsr & __RTA_ARM_MODE_MASK) == __RTA_ARM_MODE_USER);
#endif

  RX_IRQ_DISABLE();                                       // Disable RTA Rx Interrupt (required to stop incoming messages)
  TX_IRQ_DISABLE();                                       // Disable RTA Tx Interrupt
#ifdef __RTX
  if (bUserMode) tsk_lock();                              // Disable RTX OS Interrupt (if in user mode)
#endif

  // Special case for sync (and reset) messages
  if (format != MSG_FORMAT_TASKSWITCH) {
    if ((type == RTA_CMD_UNKNOWN) || (type == RTA_CMD_SYNC)) {   
      // Have to reset the states and buffer pointers here with TX IRQ disabled so it is safe
      rta.stateMachine = RTA_STATE_COMMAND;
      OUT_BUF_RESET();                                    // Set buffer empty condition
      rta.tx_seq_no = RTA_INITIAL_SEQ_NO;                 // Reset sequence number
    }
  }

  /* Check there is enough buffer for the message, otherwise discard it
     Note: We leave at least RTA_MAX_MSG_LEN in the buffer at all times
     for req/rsp messages from the host */
  bufNeeded = (format == MSG_FORMAT_LONG) ? length : 1;   // Message length
  if ((!(type & RTA_REQ_RSP_BIT)) || (format == MSG_FORMAT_TASKSWITCH)) {
    bufNeeded += (RTA_MAX_MSG_LEN/4);                     // Buffer reserved for req/rsp messages
    if (type == RTA_CMD_ERROR) {                          // Buffer reserved for error messages
      bufNeeded--;
    }
  }

  /* If there is no buffer free, send a buffer overrun message to host and
     discard the original message */
  bufLeft = ((rta.out.rd_idx - rta.out.wr_idx - 1) & RTA_OUT_MASK);
  if (bufLeft < bufNeeded) {                              // Buffer free    
    /* Check to see if we have already sent a buffer overrun message. If we have then
       it may still be waiting in the buffer. We cannot add another until it is sent
       otherwise we risk breaking sync. */
    retVal = RTA_ERR_BUF_OVERRUN;
    if (RTA_BUFFER_OVERRUN) {
      goto end;                                           // return
    }            
    rta.status |= RTA_STATUS_BUF_OVERRUN;

    /* Don't send errors for term data in blocking mode */
    #if __RTA_TERM_W_BLOCKING                         
      if (type != RTA_CMD_TERM_DATA) {
    #endif
      // Configure the buffer overrun message         
      msg->header.split.type = RTA_CMD_ERROR;     
      length = msg->header.split.length = RTA_ERR_BUF_OVERRUN;   
      format = MSG_FORMAT_SHORT;
    #if __RTA_TERM_W_BLOCKING
      }
      else {
        goto end;                                         // return
      }
    #endif
  } 
  else {
    rta.status &= ~RTA_STATUS_BUF_OVERRUN;
  }

  // First put the sequence number into the header
  if (format != MSG_FORMAT_TASKSWITCH) {
    msg->header.split.fixed = RTA_TX_MAGIC_NO;
    msg->header.split.seq_no = (unsigned int)rta.tx_seq_no++;
  }

  // Now write header (or short message) to the buffer
  OUT_BUF_WR(msg->header.raw);

  // Write the long message
  if (format == MSG_FORMAT_LONG) {
    __RTA_Flags |= FLAG_DABT_PROTECT;
    for (; length>0; length--) {      
      /* type reused as temp data store */
      type = __RTA_rd_adr((unsigned int *)data++, 0);
      OUT_BUF_WR(type);
    }
    __RTA_Flags &= ~FLAG_DABT_PROTECT;
  }

end:

#ifdef __RTX
  if (bUserMode) tsk_unlock();                  // Re-enable RTX OS Interrupt (if in user mode)
#endif
  TX_IRQ_ENABLE();                              // Enable RTA Tx Interrupt
  RX_IRQ_ENABLE();                              // Re-enable RTA Rx Interrupt
                                            
  return (retVal);
}


/*
 *  RTA Transmit word possible
 *    Parameters:      None
 *    Return Value:    0 = Not possible, Non-zero = possible
 */
#if (__RTA_HW_TYPE == RTA_HW_POLLED)
#pragma push
#pragma arm
static __forceinline int RTA_tx_word_poss (void)
{
  int r;
  TX_WORD_POSS;
  return (r);
}
#pragma pop
#endif /* if (__RTA_HW_TYPE == RTA_HW_POLLED) */

/*
 *  RTA Transmit word (interrupt context)
 *    Parameters:      None
 *    Return Value:    None
 */
#pragma push
#pragma arm
#if (RTA_EXPORT_IRQS)
void RTA_tx_word_ext (void) {
#else
static __irq void RTA_tx_word (void) {
#endif
  unsigned int tx_word;

  TX_IRQ_ACK();                                 // Acknowledge Interrupt


  if (OUT_BUF_EMPTY()) {                        // Check for buffer empty
#if (__RTA_HW_TYPE == RTA_HW_POLLED)
  }
  else {
    if (RTA_tx_word_poss()) {                   // Check TX buffer Free
      tx_word = OUT_BUF_RD();                   // Write word to the RTA    
      TX_WORD();                                // Write word to hardware                                             
    }
  }
#else
    TX_IRQ_DISABLE();                           // Disable RTA Tx Interrupt                       
  }
  else {                                        // Write data if buffer not empty      
    tx_word = OUT_BUF_RD();                     // Write word to the RTA    
    TX_WORD();                                  // Write word to hardware                                                  
  }
#endif /* #if (__RTA_HW_TYPE == RTA_HW_POLLED) */
}
#pragma pop


/*
 *  RTA Default Interrupt (only used when interrupts are used)
 *    Parameters:      None
 *    Return Value:    None
 */
#pragma push
#pragma diag_remark 177                 // Temporarily disable unused function warning
__RTA_DEC static __irq void RTA_def_irq (void) {
  DEF_IRQ_ACK();
}
#pragma pop  

/*==============================================================================
   RTA Terminal Emulator Functions 
==============================================================================*/

#if (__RTA_TERM_SUPPORT)

/*     
 *  Check is there is a character available in the terminal emulator buffer
 *    Parameters:      None
 *    Return Value:    Number of characters in buffer
 */
__RTA_DEC unsigned int RTA_TermIsKey (void) {
  return (TERM_IN_BUF_NOT_EMPTY());
}

/*
 *  Get a character from the terminal. This function blocks until a
 *  character is available
 *    Parameters:      None
 *    Return Value:    Character read from terminal
 */
__RTA_DEC unsigned int RTA_TermGetChar (void) {
  int ch;

  while (TERM_IN_BUF_EMPTY());              // Block waiting for character

  ch = TERM_IN_BUF_RD();                    // Read char from buffer

#if (__RTA_TERM_ECHO)
  RTA_TermPutChar(ch);                      // Echo the character back to the serial window
#endif
   
  return (ch);
}

/*
 *  Write a character to the terminal
 *    Parameters:      ch:    Character to write to the terminal
 *    Return Value:    Character written to the terminal
 */
__RTA_DEC unsigned int RTA_TermPutChar (unsigned int ch) {

#if (__RTA_TERM_W_BLOCKING)
  RTA_STATUS status;
  int iRetryCount = RTA_TERM_RETRY_COUNT;

  do {
    status = RTA_Msg(RTA_CMD_TERM_DATA, &ch, RTA_SHORT_MSG);
  } while ((status == RTA_ERR_BUF_OVERRUN) && RTA_HOST_CONNECTED && (--iRetryCount > 0));
#else
  RTA_Msg(RTA_CMD_TERM_DATA, &ch, RTA_SHORT_MSG);
#endif

  return (ch);
}

#endif /* #if (__RTA_TERM_SUPPORT) */

#else /* #if (__RTA_ENABLED) */
/*==============================================================================
   RTA MAIN CODE (DISABLED)
==============================================================================*/                 

RTA_STATUS RTA_Init (void) {
  return (RTA_ERR_DISABLED);
}

#endif /* #if (__RTA_ENABLED) */



/*==============================================================================
   Assembler Routines (ARM code)
==============================================================================*/

#pragma arm


#if (__RTA_ENABLED)
/*
 *  Read memory for the data out buffer. This must be a
 *  function call as it needs to be written in 
 *  ASM so that register locations are predicatable
 *  for the Data Abort handler as is may cause a data abort
 *    Parameters:      addrData:   address to read
 *    Return Value:    Data read
 */
__asm unsigned int __RTA_rd_adr (unsigned int *addrData, unsigned int r1) {
        LDR     R0,[R0,#0]                  ; Load the data at addrData (possible data abort)
        BX      LR                          ; Return
}

/*
 *  Write memory (8, 16 or 32 bits). This must be a
 *  function call as it needs to be written in 
 *  ASM so that register locations are predicatable
 *  for the Data Abort handler as is may cause a data abort
 *    Parameters:      addrData:   address to read
 *    Return Value:    Data read
 */
__asm void __RTA_wr_8 (unsigned int addrData, unsigned int data) {
        STRB    R1,[R0,#0]                  ; Store the data at addrData (possible data abort)
        BX      LR                          ; Return
}

__asm void __RTA_wr_16 (unsigned int addrData, unsigned int data) {
        STRH    R1,[R0,#0]                  ; Store the data at addrData (possible data abort)
        BX      LR                          ; Return
}

__asm void __RTA_wr_32 (unsigned int addrData, unsigned int data) {
        STR     R1,[R0,#0]                  ; Store the data at addrData (possible data abort)
        BX      LR                          ; Return
}
#endif /* #if (__RTA_ENABLED) */

/*
 *  DAbt_Error()
 *
 *  If this function executes it indicates that a
 *  data abort has occurred. This function can be 
 *  overriden by defining RTA_EXT_DABT_ERROR = 1
 *  and writing your own DAbt_Error() function to
 *  handle this error. DAbt_Handler must not be
 *  overridden directly as it is required by the
 *  Real-Time Agent
 */
#if (RTA_EXT_DABT_ERROR)

extern __asm void DAbt_Error (void);

#else

__asm void DAbt_Error (void) { 
        B      DAbt_Error                   ; Endless loop - Data Abort error occurred
}     

#endif

/*
 *  DAbt_Handler()
 *
 *  This function handles expected data aborts that
 *  occur during normal operation of the Real-Time
 *  Agent. To handle the Data Aborts in user code,
 *  override the DAbt_Error() function above
 *  R0 and R1 will be available to this function
 *  if the abort occurred in __RTA_rd_adr()
 */
__asm unsigned int DAbt_Handler (void) {
  #if (RTA_EXT_DABT_ERROR)
        IMPORT  DAbt_Error                  ; Import the DAbt_Error() address
  #endif
        IMPORT  __RTA_Flags                 ; Import the __RTA_Flags variable
        LDR     R1,=__RTA_Flags             ; Load the __RTA_Flags address
        LDR     R0,[R1]                     ; Load the __RTA_Flags variable
        ANDS    R1,R0,#FLAG_DABT_PROTECT    ; Check the FLAG_DABT_PROTECT flag
        BEQ     DAbt_Error                  ; Branch to the DAbt_Error if ~FLAG_DABT_PROTECT
        LDR     R0,=__RTA_NO_MEM_FLAG       ; Move No_Mem_Flag into R0
        SUBS    PC,LR,#4                    ; Return past the data abort instruction        
}






















/*==============================================================================
   I/O Retargetting Code
==============================================================================*/

// Serial routines
extern int sendchar (int ch);
extern int getkey (void);

#if (__IO_RETARGET_ENABLED)

#include <stdio.h>
#include <string.h>
#include <rt_misc.h>
#include <rt_sys.h>

#pragma import(__use_no_semihosting_swi)

/* Standard IO device handles - arbitrary, but any real filesystem handles must be
   less than 0x8000. */
#define STDIN     0x8001
#define STDOUT    0x8002
#define STDERR    0x8003
#define RTADBGIN  0x8004
#define RTADBGOUT 0x8005

struct __FILE { 
  int handle; 
};

/*--------------------------- _ttywrch --------------------------------------*/

void _ttywrch (int ch) {
  RTA_TermPutChar (ch);
}


#ifdef __MICROLIB             // MicroLIB only has stdio stream, no other file IO

int fputc(int ch, FILE *f) {
  int retVal;
  #if (__IO_RETARGET_STDIO_IN_USE)        
    #if (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_COM_1)
      retVal = sendchar(ch);
    #elif (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA)
      retVal = RTA_TermPutChar(ch);
    #endif
  #else /* #if (__IO_RETARGET_STDIO_IN_USE) */
    retVal = ch;        // If STDIO sent to nowhere, just return 'ch'
  #endif  
  return (retVal);
}

int fgetc (FILE *f) {
  int retVal;
  #if (__IO_RETARGET_STDIO_IN_USE)        
    #if (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_COM_1)
      retVal = getkey();
    #elif (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA)
      retVal = RTA_TermGetChar();
    #endif
  #else /* #if (__IO_RETARGET_STDIO_IN_USE) */
    retVal = (-1);      // If STDIO sent to nowhere, just return '-1'
  #endif
  return (retVal);
}

int __backspace(FILE *f) {
  return (0);
}

#else /* #ifdef __MICROLIB */ 

/* Standard IO device name defines. */
const char __stdin_name[]  = "STDIN";
const char __stdout_name[] = "STDOUT";
const char __stderr_name[] = "STDERR";

#if (__IO_RETARGET_FOPEN_ETC_ENABLED)
  #include <file_config.h>    // Header file containing definitions for... 
  /* __fopen, __fclose, __write, __flushbuf, __read, __setfpos, __get_flen */
#endif

/*--------------------------- _sys_open -------------------------------------*/

FILEHANDLE _sys_open (const char *name, int openmode) {
  /* Register standard Input Output devices. */
  if (strcmp(name, "STDIN") == 0) {
    return (STDIN);
  }
  if (strcmp(name, "STDOUT") == 0) {
    return (STDOUT);     
  }
  if (strcmp(name, "STDERR") == 0) {      
    return (STDERR);
  }
  
  /* Register Real-Time Agent debug */
  if (strcmp(name, "RTADBGIN") == 0) {
    return (RTADBGIN);
  }
  if (strcmp(name, "RTADBGOUT") == 0) {
    return (RTADBGOUT);
  }

  #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
    return (__fopen (name, openmode));
  #else
    return (0);
  #endif
}

/*--------------------------- _sys_close ------------------------------------*/

int _sys_close (FILEHANDLE fh) {
  if (fh > 0x8000) {
    return (0);
  }
  #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
    return (__fclose (fh));
  #else
    return (0);
  #endif
}

/*--------------------------- _sys_write ------------------------------------*/

int _sys_write (FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode) {  
  int retVal = (-1);

  switch (fh) {
    case STDOUT:
    case STDERR:
      #if (__IO_RETARGET_STDIO_IN_USE)        
        #if (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_COM_1)
          for (  ; len; len--) {
            sendchar(*buf++);
          }
          retVal = 0;
        #elif (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA)
          for (  ; len; len--) {
            RTA_TermPutChar(*buf++);
          }
          retVal = 0;
        #endif
      #else /* #if (__IO_RETARGET_STDIO_IN_USE) */
        retVal = 0;         // If STDIO sent to nowhere, just return OK
      #endif
    break;

    case RTADBGOUT:
      for (  ; len; len--) {
        RTA_TermPutChar(*buf++);
      }
      retVal = 0;
    break;

    default:
      #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
        retVal = __write(fh, buf, len);
      #endif
    break;
  }

  return (retVal);
}

/*--------------------------- _sys_read -------------------------------------*/

int _sys_read (FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) {
  int retVal = (-1);

  switch (fh) {
    case STDIN:
      /* only read one byte at a time */
      #if (__IO_RETARGET_STDIO_IN_USE)        
        #if (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_COM_1)
          if (len) {
            *buf++ = getkey();
          }
          retVal = (len-1);
        #elif (__IO_RETARGET_STDIO_ROUTE == __IO_RETARGET_STREAM_RTA)
          if (len) {
            *buf++ = RTA_TermGetChar();
          }
          retVal = (len-1);
        #endif
      #else /* #if (__IO_RETARGET_STDIO_IN_USE) */
        retVal = 0;         // If STDIO sent to nowhere, just return OK
      #endif
    break;

    case RTADBGIN:
      /* only read one byte at a time */
      if (len) {
        *buf++ = RTA_TermGetChar();
      }   
      retVal = (len-1);
    break;

    default:
      #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
        retVal = __read(fh, buf, len);
      #endif
    break;
  }

  return (retVal);
}

/*--------------------------- _sys_istty ------------------------------------*/

int _sys_istty (FILEHANDLE fh) {
  if (fh > 0x8000) {
    return (1);
  }
  return (0);
}

/*--------------------------- _sys_seek -------------------------------------*/

int _sys_seek (FILEHANDLE fh, long pos) {
  if (fh > 0x8000) {
    return (0);
  }
  
  #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
    return (__setfpos (fh, pos));
  #else
    return (-1);
  #endif
}

/*--------------------------- _sys_ensure -----------------------------------*/

int _sys_ensure (FILEHANDLE fh) {
  if (fh > 0x8000) {
    return (-1);
  }

  #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
    return (__flushbuf (fh));
  #else
    return (-1);
  #endif
}

/*--------------------------- _sys_flen -------------------------------------*/

long _sys_flen (FILEHANDLE fh) {
  if (fh > 0x8000) {
    return (0);
  }

  #if (__IO_RETARGET_FOPEN_ETC_ENABLED)
    return (__get_flen (fh));
  #else
    return (0);
  #endif
}

/*--------------------------- _sys_tmpnam -----------------------------------*/

int _sys_tmpnam (char *name, int sig, unsigned maxlen) {
  return (1);
}

/*--------------------------- _sys_command_string ---------------------------*/

char *_sys_command_string (char *cmd, int len) {
  return (cmd);
}


#endif /* #ifdef __MICROLIB */

/*--------------------------- _sys_exit -------------------------------------*/

void _sys_exit (int return_code) {
  /* Endless loop. */
  while (1);
}

#endif /* #if (__IO_RETARGET_ENABLED) */




